BASIC Menus
Volume Number: 7
Issue Number: 1
Column Tag: BASIC School
Menus in QuickBASIC 
By Steven Leach, Santa Clara, CA
Using MENU Resources in Microsoft QuickBASIC
Now that Microsoft has released QuickBASIC for the Macintosh it has become
possible to access the entire Macintosh ROM using the ToolBox call. This article
describes the use of these ToolBox calls to utilize MENU resources. This use is not
described at all in the QuickBASIC manual, nor in any of the example programs that are
supplied with QuickBASIC. I have supplied actual tested code, that will allow you to see
how each of the routines are used, and will describe the pitfalls that await the user of
these calls.
Warning!! This type of programming is not for the faint of heart, make any
mistakes, and the best you can expect is that nothing happens. The more likely result of
not following the rules that I describe later is an instant bomb, and the need for a
manual reset using the programmer’s switch. You may be asking yourself at this point
why should I go to all this trouble when QuickBASIC gives me the MENU functions to
perform these operations already? My answer is no reason at all unless you want to
follow the Macintosh interface guidelines, put icons in your menus, or access the full
power of the Macintosh menu system.
Resource Rules
Before I describe the routines and how to use them let me state the rules of using
these calls, and how to avoid problems. I will also describe some of the resources that I
will discuss.
The following rules apply only if you are going to use your routines in the
interpreter mode of QuickBASIC
1) Never use a MENU resource that has the same ID number as one of the
QuickBASIC MENU resources, or the same MenuID as QuickBASIC. This means that the
resource ID’s of your MENU resources should not be in the range 256-262 , and the
number of the MenuID should not be in the range of 1-7. This last number is the one
that is returned in the function MENU(0). The first number is the unique ID that is
seen when you open up the MENU resource inside ResEdit.
2) Never use a DLOG resource that has the same ID number as one of the DLOG
resources used by QuickBASIC. That means that dialog boxes that you use in your
program should not have a resource ID number in the range 128-145. The reason for
this is that if you need to perform a search and your DLOG resource has the same ID
number as the search DLOG, your dialog box will be shown not the one that QuickBASIC
uses for searching. As you can imagine this can cause all sorts of problems, and funny
situations.
3) Always initialize any and all variables that you use in any ToolBox call.
Failure to do so will result in many spectacular bombs. Because of this, and other
reasons I suggest that you always save your program before you tell the interpreter to
start running the program. If this program is a minor revision and you can keep the
changes in your head, then go for it. I always manage somehow.
The following rules apply whether you are using the interpreter or a compiled
version of your program.
1)The MENU(0) function will always return one less than the ResEdit MenuID.
For example, in my example program, my file menu has a ResEDit MenuID of 10, but
the QuickBASIC MENU(0) function returns an ID of 9. This is because QuickBASIC,
starts numbering the menus from zero. The MENU(1) function returns the proper
code, so no problem here.
2)Do Not remove the open and close braces which I have placed around many of
the variables that are referenced in the various ToolBox functions. Without the braces
the information is not passed properly, and so you will get nothing but garbage in your
menus.
3)If you place these toolbox calls in subroutines be sure to use braces around the
same information when you call the subroutine.
4) If you use ICON’s in you MENU resources remember they must be numbered
in the range 256-512, and you access them as 1,2,.... 255 not by their resource ID.
This basically means the number you feed to the ToolBox routines is the icon resource
ID - 255.
5) Be sure to transfer the resources over using ResEdit when you compile the
application. QuickBasic doesn’t do this for you except for a few resources.
6) Note the subroutines which I have provided to convert from BASIC variable to
Pascal variable types the Macintosh ROMs require. These routines are necessary to
convert the 4 character resource string that is used in BASIC to the 4 byte variable
that is used by the Macintosh ROM. The other routines convert the style string that is
customarily used in the resource compilers into an integer that is compatible with the
Macintosh ROM and vice versa. Also note the intermittent use of the BASIC SADD
function in order to send the address of a string variable to the ROM routine, in some
cases using the SADD function is deadly. I have experimented with all these routines on
a Mac Plus, Mac SE and a Mac II to make sure they work properly. The lesson is change
them at your own risk.
The Calls
Those are the “rules” to follow, if you follow them diligently all will be well, if
you don’t; good luck. Now for a description of the Calls and what they can be used for.
In each of the QuickBASIC calls you must specify the type of return if any by using a
single or double letter code. As you can see from the listing only four of the functions
associated with Menus return a value, in most cases a handle to a menu, in the other
case an integer number corresponding to the number of items in the menu. I have used
a “Q” following each function in order to disable the argument checking function that is
built into QuickBASIC. If you wish you may use the specially converted ResEdit that is
supplied with the QuickBASIC to create argument checking functions for each of these
calls.
With each of the functions I have provided a Trap value that is used to call the
particular ROM routine, an example template of the ToolBox call, and the argument
checking template that can be inputted using the QuickBASIC converted ResEdit. At this
point I would like to thank Stephen Chernicoff the author of Macintosh Revealed, which I
used extensively, and of course the authors and editors of Inside Macintosh.
The example program I have included starts off by reading the MENU resources
from it’s own resource fork, and then sets up a processing loop to perform the various
functions when the user selects an item from the function menu. I don’t perform any
cut,copy paste so I just trap this function and print out the choice you made. The Graph
Menu and File Menus show some of the reasons you may decide that using resource
MENU’s instead of application built ones are more fun and just as easy to use.
By using the function provided in the Function Menu you can change any of the
current menus,load another resource menu that you have created in ResEdit, or create a
new menu and add items to it. This simple program does not allow you to save your
work, although you could change the File Menu to include a save function and then use
the WriteRes or AddRes functions that are described in the QuickBASIC manual.
The general procedure that I have implemented in using these functions in any of
my QuickBASIC programs is as follows:
1) Create a BASIC program with a minimal amount of code to act as a holding
place for the resources.
2) Use ResEDit to create the necessary resources in that QuickBASIC file.
Remembering to write down the Resource ID numbers and other ID’s. For example, in
the dialog boxes I use to prompt the user for information to feed the ToolBox calls, I
must specifically reference each element by number.
3) Save my work when ResEdit asks me to save the work I have done.
4) Use the ToolBox functions instead of the BASIC Menu functions to change the
state and look of the menus. If you try to use the QuickBASIC Menu function, to change
any of the menus you have brought in as resources you will only cause problems for
yourself. It’s OK to use the MENU(0) and MENU(1) functions to determine which
menus the user has selected.
REM Define function to get MenuID from MenuHandle that is in memory
DEF FN GetMenuID(MenuHandle&) = PEEKW(PEEKL(MenuHandle&))
REM initialize QuickBASIC toolBox routines This is a must !!!!
ToolBox "I
REM these are the Toolbox Trap values and examples of how to use the
ToolBox calls
REM I have also included the Values for the MTBS resource template
for error checking
REM In that case you can elect not to put in the Q i.e. use "P" not
"PQ
ReleaseResource% = &HA9A3
REM ToolBox "PQ",ReleaseResource%,(MenuHandle&)
DrawMenuBar% = &HA937
REM ToolBox "PQ",DrawMenuBar%
NewMenu% = &HA931
REM ToolBox
"LQ",NewMenu%,(MenuID%),SADD(Pascal.MenuTitle$),MenuHandle&
GetMenu% = &HA9BF
REM ToolBox "LQ",GetMenu%,(MenuRsrcID%),MenuHandle&
DisposeMenu% = &HA932
REM ToolBox "PQ",DisposeMenu%,(MenuHandle&)
InsertMenu% = &H935
REM ToolBox "PQ",InsertMenu%, (MenuHandle&),(beforeID%)
ClearMenuBar% = &HA934
REM ToolBox "PQ",ClearMenuBar%
AppendMenu% = &HA933
REM ToolBox "PQ",AppendMenu%,(MenuHandle&),SADD(Pascal.defString$)
AddResMenu% = &HA94D
REM ToolBox "PQ",AddResMenu%,(MenuHandle&),(ResType&)
InsertResMenu% = &HA951
REM ToolBox
"PQ",InsertResMenu%,(MenuHandle&),(ResType&),(afterItem%)
CountMItems% = &HA950
REM ToolBox "WQ",CountMItems%,(MenuHandle&),NMenuItems%
DeleteMenu% = &HA936
REM ToolBox "PQ",DeleteMenu%,(MenuID%)
GetMHandle% = &HA949
REM ToolBox "LQ",GetMHandle%,(MenuID%),MenuHandle&
SetItem% = &HA947
REM ToolBox
"PQ",SetItem%,(MenuHandle&),(theItem%),SADD(Pascal.itemString$)
GetItem% = &HA946
REM ToolBox "PQ",GetItem%,(MenuHandle&),(theItem%),itemString$
DisableItem% = &HA93A
REM ToolBox "PQ",DisableItem%,(MenuHandle&),(theItem%)
EnableItem% = &HA939
REM ToolBox "PQ",EnableItem%,(MenuHandle&),(theItem%)
SetItemStyle% = &HA942
REM ToolBox "PQ",SetItemStyle%,(MenuHandle&),(theItem%),(theStyle%)
GetItemStyle% = &HA941
REM ToolBox "PQ",GetItemStyle%,(MenuHandle&),(theItem%),theStyle%
CheckItem% = &HA945
REM ToolBox "PQ",CheckItem%,(MenuHandle&),(theItem%),(Checked%) (
0,1)
SetItemMark% = &HA944
REM ToolBox "PQ",SetItemMark%,(MenuHandle&),(theItem%),(markChar%)
GetItemMark% = &HA943
REM ToolBox "PQ",GetItemMark%,(MenuHandle&),(theItem%),markChar%
SetItemIcon% = &HA940
REM ToolBox "PQ",SetItemIcon%,(MenuHandle&),(theItem%),(iconNum%)
GetItemIcon% = &HA93F
REM ToolBox "PQ",GetItemIcon%,(MenuHandle&),(theItem%),iconNum%
SetMenuFlash% = &HA94A
REM ToolBox "PQ",SetMenuFlash%,(flashCount%)
FlashMenuBar% = &HA94C
REM ToolBox "PQ",FlashMenuBar%,(MenuID%)
True% = (1<2)
False% = (1>2)
REM Initialize some variables and arrays that are used to keep track
of the Menus, and their states
res.ref% = 0
DIM MenuHandle&(10),ResMenu%(10),MenuID%(10)
ResType& = 0&
Dialog.Hnd& = 0&
tMenuHandle& = 0&
Num.of.Menu% = 5
res.ref% = SYSTEM(7)
REM Delete File and Edit Menu that QuickBASIC pout up when you are
using the interpretor
REM Remove these lines if you complie the program with the No
Default Menus Option.
ToolBox "PQ",DeleteMenu%,(2)
ToolBox "PQ",DeleteMenu%,(3)
REM Load in my resource Menus that included in this BASIC program
FOR indx% = 0 TO Num.of.Menu%-1
MenuRsrcID% = 263+indx%
ToolBox "LQ",GetMenu%,(MenuRsrcID%),tMenuHandle&
IF (tMenuHandle& > 0) THEN
MenuHandle&(indx%+1) = tMenuHandle&
ToolBox "PQ",InsertMenu%, (MenuHandle&(indx%+1)),(0)
ResMenu%(indx%+1) = True%
MenuID%(indx%+1) = FN GetMenuID(MenuHandle&(indx%+1))
ELSE
PRINT indx% "Has an invalid Menu handle
STOP
END IF
NEXT
REM now that all the MENU resources are in memory Draw the Menu Bar
to show them.
ToolBox "PQ",DrawMenuBar%
REM This is the Main processing loop that checks for Menu activity
Quit% = False%
CLS
WHILE MOUSE(0) <> 0 : WEND
WHILE NOT Quit%
Menu0 = MENU(0)+1
menu1 = MENU(1)
MENU
IF (Menu0 >=10 ) THEN
ON Menu0 - MenuID%(1)+1 GOSUB
FileMenu,EditMenu,menu1,Menu2,Menu3
PRINT Menu0,MENU(1)
END IF
WEND
REM Dispose of all menu handles to free memory that was allocated by
program and user
REM Note the use of two forms of memory deallocation
REM One to resource MENU's and one for menus built from scratch.
FOR indx% = 1 TO Num.of.Menu%